#include "FishControl.h"
#include "DBManger.h"
#include "MacDefind.h"
#include <FunctionalInterrupt.h>
#include "AliIoTControl.h"
#include <TimeLib.h>

FishControl::FishControl(uint32_t pin_in, uint32_t pin_pwm0, uint32_t pin_pwm1)
    : _pin_in(pin_in), _pin_pwm0(pin_pwm0), _pin_pwm1(pin_pwm1), _st_lamp(0), _st_last_lamp(0), _push_touch(0), _plus_flags(-1), _need_update(false)
{
    pinMode(_pin_in, INPUT_PULLUP);
    pinMode(_pin_pwm0, OUTPUT);
    pinMode(_pin_pwm1, OUTPUT);
    digitalWrite(_pin_pwm0, 0);
    digitalWrite(_pin_pwm1, 0);
}

FishControl::~FishControl()
{
}

void FishControl::init()
{
    noInterrupts();
    attachInterrupt(_pin_in, std::bind(&FishControl::procISR, this), CHANGE);
    interrupts();

    dbManger.loadLampValue(&lightVal);
}

void FishControl::setLamp(uint8_t state, bool save)
{
    _st_lamp = state;
    Restart();
    if (save)
        dbManger.setLampType(_st_lamp);
}

uint8_t FishControl::getLamp()
{
    return _st_lamp;
}

int32_t FishControl::getBrightness()
{
    return lightVal[_st_lamp];
}

String FishControl::getLampValue()
{
    DynamicJsonDocument doc(50);
    doc["s"] = _st_lamp;
    doc["v"] = lightVal[_st_lamp];
    doc["t"] = now();
    String output;
    serializeJson(doc, output);
    return output;
}

void FishControl::setNextLamp(bool save)
{
    ++_st_lamp %= 4;
    Restart();
    if (save)
        dbManger.setLampType(_st_lamp);
}

void FishControl::switchOnLamp(bool on)
{
    if (on)
    {
        _st_lamp = dbManger.getLampType();
    }
    else
    {
        _st_lamp = OFF;
    }
    Restart();
}

void FishControl::setBrightness(int32_t brightness)
{
    if (brightness > 1023 || brightness < 30 || _st_lamp == OFF)
        return;
    lightVal[_st_lamp] = brightness;
    _need_update = true;
    Restart();
}

bool FishControl::Run()
{
    HT_BEGIN();

    while (1)
    {
        // Serial.printf("push Touch v: %ld %ld\r\n", _push_touch,  millis());
        if (_push_touch > 0)
        {
            HT_WAIT_UNTIL(millis() - _push_touch > 800 || _push_touch == 0);
            if (_push_touch == 0)
            {
                HT_RESTART();
            }

            if (_st_lamp == OFF)
            {
                lightVal[_st_lamp] = 0;
                _push_touch = 0;
                HT_RESTART();
            }

            // _ex_timer.start(3);
            // HT_WAIT_UNTIL(_ex_timer.expired());
            HT_DELAY(3);
            lightVal[_st_lamp] += _plus_flags;

            if (lightVal[_st_lamp] >= 1023)
            {
                _plus_flags = -1;
                _push_touch = 0;
                dbManger.setLampValue(lightVal);
                aliIotControl.updateStatus();
            }
            else if (lightVal[_st_lamp] < 30)
            {
                //限定最小值 防止完全关闭
                _plus_flags = 1;
                _push_touch = 0;
                dbManger.setLampValue(lightVal);
                aliIotControl.updateStatus();
            }

            procLamp(false);
            Serial.printf(PSTR("Long Touch : %ld %d\r\n"), millis(), lightVal[_st_lamp]);
        }
        else
        {
            HT_WAIT_UNTIL(_st_lamp != _st_last_lamp || _need_update);
            _st_last_lamp = _st_lamp;
            _need_update = false;
            procLamp();
            Serial.printf(PSTR("Short Touch : %ld %d %d\r\n"), millis(), _st_lamp, lightVal[_st_lamp]);
        }
    }

    HT_END();
}

void FishControl::procISR(void)
{
    int v = digitalRead(_pin_in);
    // Serial.printf("Touch : %ld %d\r\n", millis(), v);
    if (LOW == v)
    {
        if (_push_touch == 0)
            _push_touch = millis();
    }
    else if (HIGH == v)
    {
        if (_push_touch > 0 && millis() - _push_touch < 600)
        {
            ++_st_lamp %= 4;
            dbManger.setLampType(_st_lamp);
        }
        else if (_push_touch > 0 && millis() - _push_touch > 800)
        {
            dbManger.setLampValue(lightVal);
            aliIotControl.updateStatus();
        }
        _push_touch = 0;
    }
    Restart();
}

void FishControl::procLamp(bool notify_update)
{
    switch (_st_lamp)
    {
    case ALL_ON:
        analogWrite(_pin_pwm0, lightVal[ALL_ON]);
        analogWrite(_pin_pwm1, lightVal[ALL_ON]);
        break;
    case BLUE:
        analogWrite(_pin_pwm0, lightVal[BLUE]);
        analogWrite(_pin_pwm1, 0);
        break;
    case WHITE:
        analogWrite(_pin_pwm1, lightVal[WHITE]);
        analogWrite(_pin_pwm0, 0);
        break;
    default:
        analogWrite(_pin_pwm0, 0);
        analogWrite(_pin_pwm1, 0);
        break;
    }
    if (notify_update)
        aliIotControl.updateStatus();
}